<?php
// 应用公共文件
use think\facade\Cache;
use think\facade\Lang;

/**
 * 处理文件夹下所有文件
 */
if(!function_exists('get_dir_hand')){
    function get_dir_hand($dir,$callback=null)
    {
        if(!is_dir($dir)){
            return false;
        }
        $dirs = scandir($dir);
        foreach ($dirs as $value){
            if($value=='.'||$value=='..'){
                continue;
            }
            if(is_dir(trim($dir,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$value)){
                get_dir_hand(trim($dir,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$value,$callback);
            }else{
                if(!empty($callback)){
                    $callback(trim($dir,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$value);
                }
            }
        }
        return true;
    }
}
/**
 * 新方法
 */
if(!function_exists('get_dir_path')){
    /**
     * 获取目录下所有文件
     * @param string $dir 路径
     * @param string $type 文件类型[all/dir/file]
     * @param array  $excluded 排除的文件或文件夹
     * @param array  $only 只有文件夹或文件
     * @param boolean $has_child 是否递归
     * @param boolean $is_path 是否路径
     * @return void
     */
    function get_dir_path(string $dir,string $type="all",array $excluded=[],array $only = [],bool $has_child=false,bool $is_path=false,$dd=false):array{
        if(empty($dir)){
            return [];
        }
        if(!is_dir($dir)){
            @mkdir($dir,0777,true);
            return [];
        }
        $dir = str_replace('\\', '/', $dir);
        $dir = rtrim($dir,'/').'/';
        $dirsList = scandir($dir);
        $dirsList = array_filter($dirsList,function($item){
            return $item!='.'&&$item!='..';
        });
        $all = [];
        $filter = function ($dir,$item)use($type,$excluded,$only,$is_path,$dd){
            $path = $dir.$item;
            if(!empty($excluded)){
                if(in_array($item,$excluded)){
                    return false;
                }
            }
            if(!empty($only)){
                if(!in_array($item,$only)){
                    return false;
                }
            }
            if($type!='all'){
                if($type=='dir'&&!is_dir($path)){
                    return false;
                }
                if($type=='file'&&is_dir($path)){
                    return false;
                }
            }
            if($is_path){
                return $path;
            }else{
                return $item;
            }
        };
        foreach ($dirsList as $key => $value){
            if($has_child){
                if(is_dir($dir.$value)){
                    $tem = $filter($dir,$value);
                    if(!empty($tem)){
                        $all[] = $tem;
                    }
                    $all = array_merge($all,get_dir_path(dir:$dir.$value,type:$type,excluded: $excluded,only: $only,has_child: $has_child,is_path: $is_path));
                }else{
                    $tem = $filter($dir,$value);
                    if(!empty($tem)){
                        $all[] = $tem;
                    }
                }
            }else{
                $tem = $filter($dir,$value);
                if(!empty($tem)){
                    $all[] = $tem;
                }
            }
        }
        $all = array_unique($all);
        return $all;
    }
}

/**
 * 文件获取类名
 */
if(!function_exists('file_get_class')){
    function file_get_class($file){
        if(is_file($file)&&strpos($file,'.php')!==false){
            $file = str_replace('/',DIRECTORY_SEPARATOR,$file);
            $className = str_replace('.php','',str_replace(root_path(),'',$file));
            $className = str_replace(DIRECTORY_SEPARATOR,'\\',$className);
            if(class_exists($className)){
                return $className;
            }
        }
        return false;
    }
}
/**
 * 获取插件信息
 */
if(!function_exists('get_addons_info')){
    function get_addons_info(string $addons_name){
        $addons_dir = root_path().'addons';
        if(is_file($addons_dir.DIRECTORY_SEPARATOR.$addons_name.DIRECTORY_SEPARATOR.'info.ini')){
            $config = parse_ini_file($addons_dir.DIRECTORY_SEPARATOR.$addons_name.DIRECTORY_SEPARATOR.'info.ini');
            return $config;
        }
        return [];
    }
}
if(!function_exists('set_app_config')){
    function set_app_config($app_name,$data){
        $list = get_app_config($app_name);
        foreach ($list as $key=>$value){
            if(isset($data[$value['name']])){
                $value['value'] = $data[$value['name']];
            }
            $list[$key] = $value;
        }
        return set_app_fullconfig($app_name,$list);
    }
}
/**
 * 设置插件配置
 */
if(!function_exists('set_addons_config')){
    function set_addons_config($addons_name,$data)
    {
        $list = get_addons_config($addons_name);
        foreach ($list as $key=>$value){
            if(isset($data[$value['name']])){
                $value['value'] = $data[$value['name']];
            }
            $list[$key] = $value;
        }
        return set_addon_fullconfig($addons_name,$list);

    }
}
if(!function_exists('set_app_fullconfig')){
    function set_app_fullconfig($app_name,$data){
        $fileDir = root_path().'app'.DIRECTORY_SEPARATOR.$app_name.DIRECTORY_SEPARATOR.'config.php';
        if (! is_really_writable($fileDir)) {
            throw new Exception('文件没有写入权限');
        }
        if ($handle = fopen($fileDir, 'w')) {
            fwrite($handle, "<?php\n\n".'return '.varexport($data, true).";\n");
            fclose($handle);
        } else {
            throw new Exception('文件没有写入权限');
        }

        return true;
    }
}
/**
 * 设置插件配置
 */
if(!function_exists('set_addon_fullconfig')){
    function set_addon_fullconfig($addons_name,$data)
    {
       $fileDir = root_path().'addons'.DIRECTORY_SEPARATOR.$addons_name.DIRECTORY_SEPARATOR.'config.php';
        if (! is_really_writable($fileDir)) {
            throw new Exception('文件没有写入权限');
        }
        if ($handle = fopen($fileDir, 'w')) {
            fwrite($handle, "<?php\n\n".'return '.varexport($data, true).";\n");
            fclose($handle);
        } else {
            throw new Exception('文件没有写入权限');
        }

        return true;
    }
}
if (! function_exists('varexport')) {
    /**
     * var_export方法array转[]
     *
     * @param $expression
     * @param  bool  $return
     *
     * @return mixed|string|string[]|null
     */
    function varexport($expression, $return = false)
    {
        $export = var_export($expression, true);
        $export = preg_replace("/^([ ]*)(.*)/m", '$1$1$2', $export);
        $array = preg_split("/\r\n|\n|\r/", $export);
        $array = preg_replace(["/\s*array\s\($/", "/\)(,)?$/", "/\s=>\s$/"], [null, ']$1', ' => ['], $array);
        $export = join(PHP_EOL, array_filter(["["] + $array));
        if ((bool) $return) {

            return $export;
        } else {
            echo $export;
        }
    }
}
if(!function_exists('get_app_config')){
    function get_app_config(string $app_name,bool $isValue=false){
        $addons_dir = root_path().'app'.DIRECTORY_SEPARATOR.$app_name.DIRECTORY_SEPARATOR.'config.php';
        if(is_file($addons_dir)){
            $config = include $addons_dir;
            if(empty($config)){
                return [];
            }
            if($isValue){
                $row = [];
                foreach ($config as $key => $value){
                    switch ($value['type']){
                        case 'selects':
                        case 'checkbox':
                        case 'images':
                        case 'files':
                        case 'timerange':
                        case 'daterange':
                        case 'datetimerange':
                        case 'range':
                        case 'array':
                            $nvalue = empty($value['value'])?[]:$value['value'];
                            if(!empty($nvalue)){
                                if(is_string($nvalue)){
                                    $nvalue = explode(',',$nvalue);
                                }
                            }
                            $value['value'] = $nvalue;
                            break;
                    }
                    $row[$value['name']] = $value['value'];
                }
                $config = $row;
            }

            return $config;
        }else{
            return [];
        }
    }
}
if(!function_exists('get_addons_config')){
    /**
     * 获取插件基本配置
     * @param string $addons_name
     * @return array|false
     */
    function get_addons_config(string $addons_name,bool $isValue=false){
        $addons_dir = root_path().'addons'.DIRECTORY_SEPARATOR.$addons_name.DIRECTORY_SEPARATOR.'config.php';
        if(is_file($addons_dir)){
            $config = include $addons_dir;
            if(empty($config)){
                return [];
            }
            if($isValue){
                $row = [];
                foreach ($config as $key => $value){
                    switch ($value['type']){
                        case 'selects':
                        case 'checkbox':
                        case 'images':
                        case 'files':
                        case 'timerange':
                        case 'daterange':
                        case 'datetimerange':
                        case 'range':
                        case 'array':
                            $nvalue = empty($value['value'])?[]:$value['value'];
                            if(!empty($nvalue)){
                                if(is_string($nvalue)){
                                    $nvalue = explode(',',$nvalue);
                                }
                            }
                            $value['value'] = $nvalue;
                            break;
                    }
                    $row[$value['name']] = $value['value'];
                }
                $config = $row;
            }

            return $config;
        }else{
            return [];
        }
    }
}

/**
 * 获取插件列表
 */
if(!function_exists('get_addons_list')){
    function get_addons_list(bool $refresh=false){
        $key_name =\app\common\service\AddonService::ADDONS_LIST;
        if(empty($has)||$refresh){
            $addons_dir = root_path().'addons';
            $list = get_dir_path(dir:$addons_dir,type:'dir');

            $has = array_filter($list,function($item) use($addons_dir){
                if(is_file($addons_dir.'/'.$item.'/info.ini')){
                    $config = parse_ini_file($addons_dir.'/'.$item.'/info.ini');
                    return $config;
                }
               return false;
            });
            Cache::set($key_name,$has);
        }
        return $has;
    }
}

/**
 * 获取启用插件列表
 */
if(!function_exists('get_state_addons')){
    function get_state_addons(bool $refresh=false)
    {
        $key_name = \app\common\service\AddonService::ADDONS_STATE;
        $has = Cache::get($key_name);
        if(empty($has)||$refresh){
            $addons_dir = root_path().'addons';
            $list = get_dir_path(dir:$addons_dir,type:'dir');

            $has = array_filter($list,function($item) use($addons_dir){
                $config = get_addons_info($item);
                if(!empty($config['state'])&&$config['state']==1){
                    return true;
                }
                return false;
            });
            $has = array_values($has);
            Cache::set($key_name,$has);
        }
        return $has;
    }
}
if(!function_exists('get_state_app')){
    function get_state_app(bool $refresh=false,$all=false)
    {
        $key_name = \app\common\service\AddonService::APP_STATE;
        $has = Cache::get($key_name);
        if(empty($has)||$refresh){
            $addons_dir = root_path().'app';
            $list = get_dir_path(dir:$addons_dir,type:'dir');

            $has = array_filter($list,function($item) use($addons_dir,$all){
                if($all){
                    return true;
                }
                $config = get_app_info($item);
                if(!empty($config['state'])&&$config['state']==1){
                    return true;
                }
                return false;
            });
            $has = array_values($has);
           Cache::set($key_name,$has);
        }
        return $has;
    }
}

if(!function_exists('get_addons_common_path')){
    /**
     * 获取插件公共文件
     * @param string $addons_name
     * @return array|mixed
     */
    function get_addons_common_path(string $addons_name){
        $addons_dir = get_addons_dir($addons_name);
        $common_path = [];
        $common_dir = $addons_dir.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'common.php';
        if(is_file($common_dir)){
            if(strlen(file_get_contents($common_dir))>7){
                $common_path['base'] = str_replace('\\','/',$common_dir);
            }
        }
        $base_path = $addons_dir.DIRECTORY_SEPARATOR.'app';
        // 加载app下的子目录下的service文件
        $dirs = get_dir_path(dir:$base_path,type:'dir');
        foreach ($dirs as $value){
            $temFiles = $base_path.DIRECTORY_SEPARATOR.$value.DIRECTORY_SEPARATOR.'common.php';
            if(is_file($temFiles)){
                if(strlen(file_get_contents($temFiles))>7){
                    $common_path[$value] = str_replace('\\','/',$temFiles);
                }
            }
        }
        return $common_path;
    }
}
if(!function_exists('get_addons_class')){
    function get_addons_class($addon)
    {
        $className = 'addons\\'.$addon.'\\'.ucfirst($addon);
        if(class_exists($className)){
            return $className;
        }else{
            return '';
        }
    }
}

if(!function_exists('get_addons_command')){
    /**
     * 获取插件命令
     * @param string $addons_name
     * @return array|mixed
     */
    function get_addons_command(string $addons_name){
        $addons_dir = get_addons_dir($addons_name);
        $command = [];
        // 加载app下的service文件
        $service_file = $addons_dir.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'command.php';
        if(is_file($service_file)){
            $tem = include $service_file;
            if(!empty($tem)){
                $command[] = array_merge($command,$tem);
            }
        }
        $base_path = $addons_dir.DIRECTORY_SEPARATOR.'app';
        // 加载app下的子目录下的service文件
        $dirs = get_dir_path(dir:$base_path,type:'dir');
        foreach ($dirs as $value){
            $temFiles = $base_path.DIRECTORY_SEPARATOR.$value.DIRECTORY_SEPARATOR.'command.php';
            if(is_file($temFiles)){
                $tem_arr = include $temFiles;
                if(!empty($tem_arr)){
                    $command = array_merge($command,$tem_arr);
                }
            }
        }
        return $command;
    }
}
if(!function_exists('get_addons_event')){
    /**
     * 获取插件事件
     */
    function get_addons_event(string $addons_name){
        $addons_dir = get_addons_dir($addons_name);
        $event = [];
        // 加载app下的service文件
        $service_file = $addons_dir.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'event.php';
        if(is_file($service_file)){
            $event[] = include $service_file;
        }
        $base_path = $addons_dir.DIRECTORY_SEPARATOR.'app';
        // 加载app下的子目录下的service文件
        $dirs = get_dir_path(dir:$base_path,type:'dir');
        foreach ($dirs as $value){
            $temFiles = $base_path.DIRECTORY_SEPARATOR.$value.DIRECTORY_SEPARATOR.'event.php';
            if(is_file($temFiles)){
                $tem_arr = include $temFiles;
                if(!empty($tem_arr)){
                    $event[] = $tem_arr;
                }
            }
        }
        $bind = [];
        $listen = [];
        $subscribe = [];
        foreach ($event as $key=>$value){
            if(!empty($value['bind'])){
                $bind = array_merge($bind,$value['bind']);
            }
            if(!empty($value['listen'])){
                foreach ($value['listen'] as $key=>$value){
                    $listen[$key] = array_merge($listen[$key]??[],$value);
                }
            }
            if(!empty($value['subscribe'])){
                $subscribe = array_merge($subscribe,$value['subscribe']);
            }
        }
        $haslisten = false;
        foreach ($listen as $key=>$value){
            if(!empty($value)){
                $haslisten = true;
                break;
            }
        }
        if($haslisten===false&&empty($subscribe)&&empty($bind)){
            return [];
        }
        return [
            'bind'=>$bind,
            'listen'=>$listen,
            'subscribe'=>$subscribe,
        ];
    }
}
if(!function_exists('get_addons_middleware')){
    /**
     * 获取插件中间件
     * @param string $addons_name
     * @return array|mixed
     */
    function get_addons_middleware(string $addons_name){
        $addons_dir = get_addons_dir($addons_name);
        $middleware = [];
        // 加载app下的service文件
        $service_file = $addons_dir.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'middleware.php';
        if(is_file($service_file)){
            $base = include $service_file;
            if(!empty($base)){
                $middleware['base'] = $base;
            }
        }
        $base_path = $addons_dir.DIRECTORY_SEPARATOR.'app';
        // 加载app下的子目录下的service文件
        $dirs = get_dir_path(dir:$base_path,type:'dir');
        foreach ($dirs as $value){
            $temFiles = $base_path.DIRECTORY_SEPARATOR.$value.DIRECTORY_SEPARATOR.'middleware.php';
            if(is_file($temFiles)){
                $tem_arr = include $temFiles;
                if(!empty($tem_arr)){
                    $middleware[$value] = $tem_arr;
                }
            }
        }
        return $middleware;
    }
}
if(!function_exists('get_addons_provider')){
    /**
     * 获取插件容器
     * @param string $addons_name
     * @return array|mixed
     */
    function get_addons_provider(string $addons_name){
        $addons_dir = get_addons_dir($addons_name);
        $provider = [];
        // 加载app下的service文件
        $service_file = $addons_dir.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'provider.php';
        if(is_file($service_file)){
            $provider = include $service_file;
        }
        $base_path = $addons_dir.DIRECTORY_SEPARATOR.'app';
        // 加载app下的子目录下的service文件
        $dirs = get_dir_path(dir:$base_path,type:'dir');
        foreach ($dirs as $value){
            $temFiles = $base_path.DIRECTORY_SEPARATOR.$value.DIRECTORY_SEPARATOR.'provider.php';
            if(is_file($temFiles)){
                $tem_arr = include $temFiles;
                if(!empty($tem_arr)){
                    $provider = array_merge($provider,$tem_arr);
                }
            }
        }
        return $provider;
    }
}

if(!function_exists('get_addons_service')){
    /**
     * 获取插件服务
     * @param string $addons_name
     * @return array|mixed
     */
    function get_addons_service(string $addons_name){
        $addons_dir = get_addons_dir($addons_name);
        $service = [];
        // 加载app下的service文件
        $service_file = $addons_dir.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'service.php';
        if(is_file($service_file)){
            $base = include $service_file;
            if(!empty($base)){
                $service['base'] = $base;
            }
        }
        $base_path = $addons_dir.DIRECTORY_SEPARATOR.'app';
        // 加载app下的子目录下的service文件
        $dirs = get_dir_path(dir:$base_path,type:'dir');
        foreach ($dirs as $value){
            $temFiles = $base_path.DIRECTORY_SEPARATOR.$value.DIRECTORY_SEPARATOR.'service.php';
            if(is_file($temFiles)){
                $tem_arr = include $temFiles;
                if(!empty($tem_arr)){
                    $service[$value] = $tem_arr;
                }
            }
        }
        return $service;
    }
}

if(!function_exists('get_addons_route')){
    /**
     * 获取插件路由
     * @param string $addons_name
     * @return void
     */
    function get_addons_route(string $addons_name){
        $addons_dir = get_addons_dir($addons_name);
        $routeList = [];
        // 加载app下的路由文件
        $route = str_replace('\\', '/', $addons_dir.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'route.php');
        if(is_file($route)){
            $str = file_get_contents($route);
            if(strlen($str)>7){
                $routeList[] = $route;
            }
        }
        $addons_app_dir = $addons_dir.DIRECTORY_SEPARATOR.'app';
        $pathList = get_dir_path(dir:$addons_app_dir,type:'dir',excluded:['route.php']);
        // 加载子目录下的路由文件
        foreach ($pathList as $value){
            if(is_dir($addons_app_dir.DIRECTORY_SEPARATOR.$value.DIRECTORY_SEPARATOR.'route')){
                $files = get_dir_path(dir:$addons_app_dir.DIRECTORY_SEPARATOR.$value.DIRECTORY_SEPARATOR.'route',type:'file',is_path: true);
                $files = array_filter($files,function ($item){
                    if(is_file($item)){
                        $str = file_get_contents($item);
                        if(strlen($str)>7){
                            return true;
                        }
                    }
                    return false;
                });
                if(!empty($files)){
                    $routeList = array_merge($routeList,$files);
                }
            }
        }
        return $routeList;
    }
}

/**
 * 获取缓存配置
 */
if(!function_exists('get_cache_config')){
    function get_cache_config($key="")
    {
        $configAll = config('cache');
        if(!empty($configAll)){
            $config = $configAll['stores'][$configAll['default']];
            if(empty($key)){
                return $config;
            }
            if(isset($config[$key])){
                return $config[$key];
            }else{
                return [];
            }
        }else{
            return [];
        }
    }
}

/**
 * 判断 文件/目录 是否可写（取代系统自带的 is_writeable 函数）
 *
 * @param string $file 文件/目录
 * @return boolean
 */
function is_write($file)
{
    if (is_dir($file)) {
        $dir = $file;
        if ($fp = @fopen("$dir/test.txt", 'wb')) {
            @fclose($fp);
            @unlink("$dir/test.txt");
            $writeable = true;
        } else {
            $writeable = false;
        }
    } else {
        if ($fp = @fopen($file, 'ab+')) {
            @fclose($fp);
            $writeable = true;
        } else {
            $writeable = false;
        }
    }
    return $writeable;
}

if(!function_exists('get_addons_dir')){
    /**
     * 获取插件目录
     * @param string $addons_name
     * @return string
     */
    function get_addons_dir(string $addons_name){
        $addons_dir = root_path().'addons';
        if(is_file($addons_dir.DIRECTORY_SEPARATOR.$addons_name.DIRECTORY_SEPARATOR.'info.ini')){
            return str_replace('\\', '/', $addons_dir.DIRECTORY_SEPARATOR.$addons_name);
        }
        return '';
    }
}
/**
 * 清理插件缓存
 */
if(!function_exists('cleanAddonsCache')){
    function cleanAddonsCache(){
        $keys = [
            \app\common\service\AddonService::ADDONS_STATE,//插件状态缓存key
            \app\common\service\AddonService::ADDONS_LIST,//插件列表缓存key
            \app\common\service\AddonService::ADDONS_INFO,//插件加载缓存key
            \app\common\service\AddonService::APP_STATE
        ];
        foreach ($keys as $key){
            Cache::delete($key);
        }
        get_state_addons(true);
        get_addons_list(true);
        getAllCache(true);
    }
}
if(!function_exists('getAllCache')){
    function getAllCache($refresh=false){
        $addon_key = \app\common\service\AddonService::ADDONS_INFO;
        $has = Cache::get($addon_key);
        $debug = \config('app.app_debug');
        if(empty($has)||!empty($debug)||$refresh){
            $has = [];
            foreach (get_addons_list() as $addon){
                $has[$addon] = [
                    'path'=>get_addons_dir($addon),
                    'info'=>get_addons_info($addon),
                    'config'=>get_addons_config($addon,true),
                    'route_path'=>get_addons_route($addon),
                    'service'=>get_addons_service($addon),
//                'provide'=>get_addons_provider($addon),
                    'middleware'=>get_addons_middleware($addon),
                    'event'=>get_addons_event($addon),
                    'command'=>get_addons_command($addon),
                    'common_path'=>get_addons_common_path($addon),
                    'class_name'=>get_addons_class($addon)
                ];
            }
            Cache::set($addon_key,$has);
        }
    }
}

/**
 * 获取插件类的类名.
 *
 * @param  string  $name  插件名
 * @param  string  $type  返回命名空间类型
 * @param  string  $class  当前类名
 *
 * @return string
 */
function get_addon_class($name, $type = 'controller', $class = null)
{
    $name = parseName($name);
    // 处理多级控制器情况
    if (! is_null($class) && strpos($class, '.')) {
        $class = explode('.', $class);
        $class[count($class) - 1] = parseName(end($class), 1);
        if($type == 'controller'){
            $tem = $class[0];
            $tem = explode('/', $tem);
            array_splice($tem, 1, 0,'controller');
            $class[0] = implode('/', $tem);
            $class = str_replace('/','\\',$class);
        }
        $class = implode('\\', $class);
    } else {
        $class = parseName(is_null($class) ? $name : $class, 1);
        if($type == 'controller'){
            $class = strtolower($class);
            $class = explode('/', $class);
            array_splice($class, 1, 0,'controller');
            $class = implode('\\', $class);

//            $class = strtolower($class).'\\controller\\Index';
        }
    }
    switch ($type) {
        case 'controller':
            $namespace = '\\addons\\'.$name.'\\'.'app'.'\\'.$class;
            break;
        default:
            $namespace = '\\addons\\'.$name.'\\'.$class;
    }
    return class_exists($namespace) ? $namespace : '';
}

if (! function_exists('parseName')) {
    function parseName($name, $type = 0, $ucfirst = true)
    {
        if ($type) {
            $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
                return strtoupper($match[1]);
            }, $name);

            return $ucfirst ? ucfirst($name) : lcfirst($name);
        }

        return strtolower(trim(preg_replace('/[A-Z]/', '_\\0', $name), '_'));
    }
}

if(!function_exists('get_query')){
    /**
     * 获取当前请求的url
     * @param $type
     * @return Closure|string
     */
    function get_query($type="url")
    {
        switch ($type){
            case 'url':
                return request()->url();
            case 'module':
                $url = request()->url();
                $url = trim($url, '/');
                $url = str_replace('/', '.', $url);
                $url = explode('.', $url);
                if(count($url) > 1){
                    return $url[0];
                }else{
                    return '';
                }
            case 'controller':
                return request()->controller();
            case 'action':
                return request()->action();
        }
        return "";
    }
}


if (! function_exists('__')) {

    /**
     * 获取语言变量值
     *
     * @param  string  $name  语言变量名
     * @param  array  $vars  动态变量值
     * @param  string  $lang  语言
     *
     * @return mixed
     */
    function __($name, $vars = [], $lang = '')
    {
        if (is_numeric($name) || ! $name) {
            return $name;
        }
        if (! is_array($vars)) {
            $vars = func_get_args();
            array_shift($vars);
            $lang = '';
        }
        return Lang::get($name, $vars, $lang);
    }
}

/**
 * 生成加密密码
 * @param $password
 * @param $salt  手动提供散列密码的盐值（salt）。这将避免自动生成盐值（salt）。,默认不填写将自动生成
 * @return string
 */
function create_password($password, $salt = '')
{
    return password_hash($password.$salt, PASSWORD_DEFAULT);
}

/**
 * 获取唯一随机字符串
 * @param int $len
 * @return string
 */
function unique_random($len = 10)
{
    $str = 'qwertyuiopasdfghjklzxcvbnmasdfgh';
    str_shuffle($str);
    return substr(str_shuffle($str), 0, $len);
}

/**
 * 校验比对密码和加密密码是否一致
 * @param $password
 * @param $hash
 * @return bool
 */
function check_password($password, $hash, $salt = '')
{
    if (!password_verify($password.$salt, $hash)) return false;
    return true;
}


if(!function_exists('app_map_get')){
    /**
     * 获取app映射
     * @param $app
     * @return mixed
     */
    function app_map_get($app,bool $isKey = true)
    {
        $config = config('app.app_map');
        if(empty($config)){
            return $app;
        }
        if($isKey){
            if(isset($config[$app])){
                return $config[$app];
            }
        }else{
            $key = array_search($app,$config);
            if($key !== false){
                return $key;
            }
        }
        return $app;
    }
}

if(!function_exists('app_site')){
    function app_site($key='')
    {
        $env_file = root_path().'.env';
        if(!is_file($env_file)){
            return [];
        }
        if(!empty($key)){
            $key_array = explode('.',$key);
            if(count($key_array) == 1 && !empty($key_array)){
                return \think\facade\Db::name('config')->where('group',$key_array[0])->column('value','name');
            }elseif (count($key_array) == 2){
                return \think\facade\Db::name('config')->where('group',$key_array[0])->where('name',$key_array[1])->value('value');
            }elseif(count($key_array)==3){
                $config = \think\facade\Db::name('config')->where('group',$key_array[0])->where('name',$key_array[1])->value('value');
                if(is_string($config)&&is_json($config)){
                    $config = json_decode($config,true);
                }
                if(isset($config[$key_array[2]])){
                    return $config[$key_array[2]];
                }
                return '';
            }
        }else{
            $config =  \think\facade\Db::name('config')->column('value','name');
            foreach ($config as $key => $value){
                if(is_string($value)&&is_json($value)){
                    $config[$key] = json_decode($value,true);
                }
            }
            return $config;
        }
    }
}

if(!function_exists('is_json')){
    // 判断是否是json
    function is_json($str)
    {
        json_decode($str);
        return json_last_error() === JSON_ERROR_NONE;
    }
}

if (! function_exists('is_really_writable')) {

    /**
     * 判断文件或文件夹是否可写.
     *
     * @param  string  $file  文件或目录
     *
     * @return bool
     */
    function is_really_writable($file)
    {
        if (DIRECTORY_SEPARATOR === '/') {
            return is_writable($file);
        }
        if (is_dir($file)) {
            $file = rtrim($file, '/').'/'.md5(mt_rand());
            if (($fp = @fopen($file, 'ab')) === false) {
                return false;
            }
            fclose($fp);
            @chmod($file, 0777);
            @unlink($file);

            return true;
        } elseif (! is_file($file) or ($fp = @fopen($file, 'ab')) === false) {
            return false;
        }
        fclose($fp);

        return true;
    }
}


/**
 * 把返回的数据集转换成Tree
 * @param $list 要转换的数据集
 * @param string $pk
 * @param string $pid
 * @param string $child
 * @param int $root
 * @return array
 */
function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = 'child', $root = 0)
{
    // 创建Tree
    $tree = array();
    if (is_array($list)) {
        // 创建基于主键的数组引用
        $refer = array();
        foreach ($list as $key => $data) {
            $refer[ $data[ $pk ] ] =& $list[ $key ];
        }
        foreach ($list as $key => $data) {
            // 判断是否存在parent
            $parent_id = $data[ $pid ];
            if ($root == $parent_id) {
                $tree[] =& $list[ $key ];
            } else {
                if (isset($refer[ $parent_id ])) {
                    $parent =& $refer[ $parent_id ];
                    $parent[ $child ][] =& $list[ $key ];
                }
            }
        }
    }
    return $tree;

}
function tree_to_level($allMenu,$level=1,$levelField="level")
{
    foreach ($allMenu as $k=>$v){
        if(isset($v['children'])&&count($v['children'])>0){
            $allMenu[$k][$levelField] = $level;
            $allMenu[$k]['children'] = tree_to_level($v['children'],$level+1,$levelField);
        }else{
            $allMenu[$k][$levelField] = $level;
        }
    }
    return $allMenu;
}

if(!function_exists('tree_to_menu')){
    function tree_to_menu($allMenu,$keyStr=''){
        $str = "";
        foreach ($allMenu as $k => $v){
            $newkey = $keyStr.$k;
            if(isset($v['children'])&&count($v['children'])>0){
                $str .= '<el-sub-menu :index="'.$v['id'].'">';
                if(!empty($v['icon'])){
                    $str .= '<template #title @click="addMain(`'.__($v['title']).'`,`'.app_map_get($v['module'],false).'`,`'.$v['route'].'`,'.$v['id'].')" :size="22"><el-icon><'.$v['icon'].' /></el-icon>'.__($v['title']).'</template>';
                }else{
                    $str .= '<template #title @click="addMain(`'.__($v['title']).'`,`'.app_map_get($v['module'],false).'`,`'.$v['route'].'`,'.$v['id'].')">'.__($v['title']).'</template>';
                }

                $str .= tree_to_menu($v['children'],$newkey.'-');
                $str .= '</el-sub-menu>';
            }else{
                if(!empty($v['icon'])){
                    $str .= '<el-menu-item :index="'.$v['id'].'" @click="addMain(`'.__($v['title']).'`,`'.app_map_get($v['module'],false).'`,`'.$v['route'].'`,'.$v['id'].')">'.'<el-icon :size="22"><'.$v['icon'].' /></el-icon>'.__($v['title']).'</el-menu-item>';
                }else{
                    $str .= '<el-menu-item index="'.$v['id'].'" @click="addMain(`'.__($v['title']).'`,`'.app_map_get($v['module'],false).'`,`'.$v['route'].'`,'.$v['id'].')">'.__($v['title']).'</el-menu-item>';
                }

            }
        }
        return $str;
    }
}

if (! function_exists('upload_file')) {
    /**
     * 上传文件.
     *
     * @param  string  $file  上传的文件
     * @param  string  $name  上传的位置
     * @param  string  $path  上传的文件夹
     * @param  string  $validate  规则验证
     * @param  string  $url  前缀
     *
     * @return string|bool
     * @author niu
     */
    function upload_file($file = null, $name = 'local', $path = '', $validate = '', $url = '/')
    {
        //文件
        if (! $file) {
            return false;
        }
        //上传配置
        $config_name = 'filesystem.disks.'.$name;
        $filesystem = config($config_name);
        if (! $filesystem) {
            return false;
        }
        //上传文件
        if ($validate) {
            validate(['file' => $validate])->check(['file' => $file]);
        }
        $savename = \think\facade\Filesystem::disk($name)->putFile($path, $file, function ($file) {
            //重命名
            return date('Ymd').'/'.md5((string) microtime(true));
        });
        if(empty($url)){
            $url = '/';
        }
        $savename = $url.$savename;

        return $savename;
    }
}

if (! function_exists('letter_avatar')) {
    /**
     * 首字母头像.
     *
     * @param $text
     *
     * @return string
     */
    function letter_avatar($text)
    {
        $total = unpack('L', hash('adler32', $text, true))[1];
        $hue = $total % 360;
        [$r, $g, $b] = hsv2rgb($hue / 360, 0.3, 0.9);

        $bg = "rgb({$r},{$g},{$b})";
        $color = '#ffffff';
        $first = mb_strtoupper(mb_substr($text, 0, 1));
        $src = base64_encode('<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="100" width="100"><rect fill="'.$bg.'" x="0" y="0" width="100" height="100"></rect><text x="50" y="50" font-size="50" text-copy="fast" fill="'.$color.'" text-anchor="middle" text-rights="admin" alignment-baseline="central">'.$first.'</text></svg>');
        $value = 'data:image/svg+xml;base64,'.$src;

        return $value;
    }
    if (! function_exists('hsv2rgb')) {
        function hsv2rgb($h, $s, $v)
        {
            $r = $g = $b = 0;

            $i = floor($h * 6);
            $f = $h * 6 - $i;
            $p = $v * (1 - $s);
            $q = $v * (1 - $f * $s);
            $t = $v * (1 - (1 - $f) * $s);

            switch ($i % 6) {
                case 0:
                    $r = $v;
                    $g = $t;
                    $b = $p;
                    break;
                case 1:
                    $r = $q;
                    $g = $v;
                    $b = $p;
                    break;
                case 2:
                    $r = $p;
                    $g = $v;
                    $b = $t;
                    break;
                case 3:
                    $r = $p;
                    $g = $q;
                    $b = $v;
                    break;
                case 4:
                    $r = $t;
                    $g = $p;
                    $b = $v;
                    break;
                case 5:
                    $r = $v;
                    $g = $p;
                    $b = $q;
                    break;
            }

            return [
                floor($r * 255),
                floor($g * 255),
                floor($b * 255),
            ];
        }
    }
}
/**
 * 复制文件夹
 */
if(!function_exists('copyDir')){
    function copyDir($src, $dst)
    {
        if(!empty($src)&&!empty($dst)){
            if (is_dir($src)) {
                $files = scandir($src);
                if(!is_dir($dst)){
                    @mkdir($dst, 0777, true);
                }
                foreach ($files as $file) {
                    if ($file != "." && $file != "..") {
                        if (is_dir($src."/".$file)) {
                            copyDir($src."/".$file, $dst."/".$file);
                        } else {
                            copy($src."/".$file, $dst."/".$file);
                        }
                    }
                }
            }
        }else{
            return false;
        }
    }
}
/**
 * 获取应用列表
 */
if(!function_exists('get_app_list')){
    function get_app_list()
    {
        $excluded = [
            'admin',
            'api',
            'index',
            'common',
            'install',
        ];
        $path = root_path().'app';
        $list =  get_dir_path(dir: $path,type: 'dir',excluded: $excluded);
        $newlist = [];
        foreach ($list as $k=>$v){
            $file = $path.'/'.$v.'/info.ini';
            if(is_file($file)){
                $newlist[] = $v;
            }
        }
        return $newlist;
    }
}
/**
 * 获取app应用配置
 */
if(!function_exists('get_app_info')){
    function get_app_info($appName)
    {
        $dir = root_path().'app/'.$appName.'/info.ini';
        if(file_exists($dir)){
            $info = parse_ini_file($dir);
            return $info;
        }else{
            return [];
        }
    }
}
/**
 * 获取数据库配置
 */
if(!function_exists('get_db_config')){
    function get_db_config($key)
    {
        if(strpos($key,'_')==false){
            $key = "db_".$key;
        }
        $key = strtoupper($key);
       return \think\facade\Env::get($key,'');
    }
}
if(!function_exists('json_encode256')){
    /**
     * 中文不转义
     * @param $data
     * @return false|string
     */
    function json_encode256($data)
    {
        return json_encode($data,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
    }
}
/**
 * 成功返回
 */
if(!function_exists('success')){
    function success(string|array|int $msg='success',array|null|string|bool $data=null,string|int $code=1,string $url='')
    {
        if(is_array($msg)){
            $data = $msg;
            $msg = 'success';
        }
        if(is_int($msg)){
            $code = $msg;
            $msg = 'success';
        }
        return json([
            'code' => $code,
            'msg' => $msg,
            'data' => $data,
            'url' => $url,
            'time'=>time()
        ]);
    }
}
if(!function_exists('error')){
    function error($msg = 'error',string|int $code = 0,$data=null,string $url = '')
    {
        if(is_array($msg)){
            $data = $msg;
            $msg = 'error';
        }
        if(is_int($msg)){
            $code = $msg;
            $msg = 'error';
        }
        $back = [
            'code' => $code,
            'msg' => $msg,
            'data' => $data,
            'url' => $url,
            'time'=>time()
        ];
        return json($back);
    }
}